import CryptoJS from "crypto-js";

// ---------- 内部工具 ----------
const xorBlock = (chunk, ivHex) => {
  // chunk：<=8个字符的 ASCII；返回 16 位 HEX
  const bytes = Array.from(chunk).map((c) => c.charCodeAt(0));
  while (bytes.length < 8) bytes.push(0);
  const iv = CryptoJS.enc.Hex.parse(ivHex);
  const out = bytes.map((b, i) => (b ^ iv.words[i >>> 1] >>> ((~i & 1) * 16)) & 0xff);
  return CryptoJS.enc.Hex.stringify(CryptoJS.lib.WordArray.create(out));
};

const desEcb = (hex8, keyHex) =>
  CryptoJS.DES.encrypt(CryptoJS.enc.Hex.parse(hex8), CryptoJS.enc.Hex.parse(keyHex), {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.NoPadding,
  }).ciphertext.toString().toUpperCase();

// ---------- 计算 K ----------
export function computeK(bodyStr, keyU) {
  if (!bodyStr.endsWith(",")) bodyStr += ",";
  const t = /T:([0-9]{10})/.exec(bodyStr)[1];
  const p = /P:([0-9A-F]{4})/.exec(bodyStr)[1];
  const s = /S:([0-9A-F]{4})/.exec(bodyStr)[1];
  let n = `${t}${p}${s.slice(-2)}`.toUpperCase();

  for (let i = 0; i < bodyStr.length; i += 8) {
    const chunk = bodyStr.slice(i, i + 8).toUpperCase();
    n = xorBlock(chunk, n);
    n = desEcb(n, keyU);
  }
  return n.slice(0, 8);
}

// 十六进制辅助
const _hex2 = (val, width = 2) => val.toString(16).toUpperCase().padStart(width, "0");

// 根据 permission 构造 Q:{...}
const buildQ = (permission) => {
  const marks = (permission.permissionMark || "").split(",").filter(Boolean);
  const hexMarks = marks.map((m) => _hex2(parseInt(m))).join("|");
  const segs = [`N1:${hexMarks}`];

  const floor = permission.permissionFloor;
  if (floor && floor !== "0") segs.push(`X1:${_hex2(parseInt(floor))}`);
  const direct = permission.directFloor;
  if (direct && direct !== "0") segs.push(`Y:${_hex2(parseInt(direct))}`);

  return `Q:{${segs.join(",")}},`;
};

// ---------- 从接口 response 拼 SDK ----------
export function buildSdk(resp) {
  const param = resp.param;
  const userid = param.userid.padStart(8, "0");
  const begin = param.beginDate;
  const keyU = param.keyU;

  const qPart = buildQ(param.permission?.[0] || {});

  const body =
    `V:10,U:${userid},M:43,H:00,` +
    `I:0001,T:${begin},P:001E,S:0001,` +
    qPart;

  const k = computeK(body, keyU);
  const L = (body.length + 10).toString(16).toUpperCase().padStart(2, "0");
  return `SDK:{L:${L},${body}K:${k}}`;
}

